package org.huamoxi.start;

import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import org.huamoxi.entity.MarketItem;
import org.huamoxi.inventory.MarketInventory;
import org.huamoxi.listener.MarketInventoryClickListener;
import org.huamoxi.util.DataSQLUtil;

import java.io.File;
import java.math.BigDecimal;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class PluginMain extends JavaPlugin {
    public static Economy econ;

    private Connection dbConnection;

    private FileConfiguration config;

    private boolean hasVault;

    @Override
    public void onEnable() {
        saveDefaultConfig();
        config = getConfig();
        ConsoleCommandSender consoleSender = getServer().getConsoleSender();
        consoleSender.sendMessage(config.getString("color.inventoryColor") + "[TradeMarketplace]" + ChatColor.AQUA + "插件加载中...");
        boolean isRunning = config.getBoolean("isRunning");
        if (isRunning) {
            hasVault = setupEconomy();
            if (hasVault) {
                consoleSender.sendMessage(config.getString("color.inventoryColor") + "[TradeMarketplace]" + ChatColor.AQUA + "config.yml中已开启插件, 继续加载...");
                // 插件启用时初始化数据库
                dbConnection = DataSQLUtil.initTable(getDataFolder().getPath() + File.separator);
                // 注册事件
                Bukkit.getPluginManager().registerEvents(new MarketInventoryClickListener(this, dbConnection), this);
                // 注册命令
                Bukkit.getPluginCommand("market").setExecutor(this);
                consoleSender.sendMessage(config.getString("color.inventoryColor") + "[TradeMarketplace]" + ChatColor.BLUE + "插件加载完成!!");
            } else {
                consoleSender.sendMessage(config.getString("color.inventoryColor") + "[TradeMarketplace]" + ChatColor.RED + "加载失败, 未安装Vault插件。");
            }
        } else {
            consoleSender.sendMessage(config.getString("color.inventoryColor") + "[TradeMarketplace]" + ChatColor.RED + "config.yml中已关闭插件, 加载已停止");
        }
    }

    @Override
    public void onDisable() {
        // 插件禁用时关闭数据库连接
        DataSQLUtil.closeDatabase(dbConnection);
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        // 判断是否是使用的 market 命令
        if (!command.getName().equalsIgnoreCase("market")) {
            return true;
        }

        Player player = (Player) sender;

        // 检查是否已经开启插件
        FileConfiguration config = getConfig();
        boolean isRunning = config.getBoolean("isRunning");
        if (!isRunning) {
            return true;
        }

        // 检查发送者是否是玩家
        if (!(sender instanceof Player)) {
            // 如果不是玩家，发送消息
            sender.sendMessage(config.getString("market.name") + config.getString("message.isNotPlayerMsg"));
            return true;
        }

        // 判断是否有加载Vault插件
        if (!hasVault) {
            sender.sendMessage(config.getString("market.name") + config.getString("message.missVaultMsg"));
            return true;
        }

        // 判断是否有权限使用
        if (!player.hasPermission("market.use")) {
            player.sendMessage(config.getString("market.name") + config.getString("message.missPermissionMsg"));
            return true;
        }

        // 判断是否正确输入指令
        if (args.length < 1) {
            sendMessageToPlayer(player);
            return true;
        }

        MarketInventory marketInventory = new MarketInventory();

        // market open
        if (args[0].equalsIgnoreCase("buy")) {
            UUID uniqueId = player.getUniqueId();
            // 存储玩家分页情况
            Integer current = DataSQLUtil.getCurrentByUID(dbConnection, uniqueId);
            if (current != 1) {
                DataSQLUtil.updateCurrentByPlayer(dbConnection, player, 1);
            }
            // 查询 MarketItem 最大页数
            Integer maxPage = DataSQLUtil.getMaxPage(dbConnection, config);
            // 打开市场面板
            marketInventory.openMarketInventory(player, config, 1, maxPage, dbConnection);
            return true;
        } else if (args[0].equalsIgnoreCase("sell")) {
            if (!(args.length == 3 || args.length == 4)) {
                sendMessageToPlayer(player);
                return true;
            }

            switch (args[0]) {
                case "sale":
                    // 一、拍卖
                    if (args.length != 4) {
                        sendMessageToPlayer(player);
                        return true;
                    }

                    break;
                case "sell":
                    // 二、出售
                    // 2.1参数校验
                    if (args.length != 3) {
                        sendMessageToPlayer(player);
                        return true;
                    }
                    // 2.1.1 <数量> 校验
                    if (!args[1].matches("[1-9]\\d*$")) {
                        player.sendMessage(config.getString("market.name") + config.getString("notice.numberInputErrorMsg"));
                        return true;
                    }
                    ItemStack itemInMainHand = player.getInventory().getItemInMainHand();
                    int amount = itemInMainHand.getAmount();
                    int arg1 = Integer.parseInt(args[1]);
                    if (arg1 > amount) {
                        player.sendMessage(config.getString("market.name") + config.getString("notice.notEnoughNumberMsg"));
                        return true;
                    }
                    // 2.1.2 <金额> 校验
                    if (!args[2].matches("(?!0\\d)\\d+(\\.\\d{2})?$")) {
                        player.sendMessage(config.getString("market.name") + config.getString("notice.amountInputErrorMsg"));
                        return true;
                    }
                    // 2.2 属性设置
                    // 获取定义的数量和价格
                    String number = args[1];
                    String price = args[2];

                    // 属性：物品类型
                    Material itemType = itemInMainHand.getType();
                    if (itemType == Material.AIR) {
                        player.sendMessage(config.getString("notice.noItemInMainHand"));
                        return true;
                    }

                    ItemMeta itemMeta = itemInMainHand.getItemMeta();
                    // 属性：物品名字
                    String displayName = "";
                    // 属性：物品描述
                    String loreStr = "";
                    if (itemMeta != null) {
                        displayName = itemMeta.getDisplayName();
                        List<String> loreList = itemMeta.getLore();
                        if (loreList != null && loreList.size() > 0) {
                            for (String lore: loreList) {
                                if (lore.length() == 0) {
                                    loreStr = lore;
                                } else {
                                    loreStr += "#desc#" + lore;
                                }
                            }
                        }
                    }

                    // 属性：物品附魔
                    String enchantStr = getEnchantJsonStr(itemInMainHand);

                    MarketItem marketItem = new MarketItem();
                    marketItem.setType(itemType.toString());
                    marketItem.setTitle(displayName != null ? displayName : "");
                    marketItem.setLore(loreStr);
                    marketItem.setPrice(new BigDecimal(price).setScale(2, BigDecimal.ROUND_HALF_UP));
                    marketItem.setQuantity(Integer.parseInt(number));
                    marketItem.setDurability(itemInMainHand.getDurability());
                    marketItem.setMaxDurability(itemType.getMaxDurability());
                    marketItem.setEnchantDescription(enchantStr);
                    marketItem.setCategory(1);
                    marketItem.setState(1);
                    marketItem.setPlayerUID(player.getUniqueId().toString());
                    marketItem.setValidity(null);
                    marketItem.setSort(1);

                    // 出售物品
                    marketInventory.sellItem(player, marketItem, amount, arg1, config, dbConnection);
                    break;
                case "lease":
                    // 出租
                    if (args.length != 4) {
                        sendMessageToPlayer(player);
                        return true;
                    }
                    break;
            }
            return true;
        }

        return true;
    }

    private static String getEnchantJsonStr (ItemStack itemStack) {
        ItemMeta itemMeta = itemStack.getItemMeta();
        String enchantStr = "";
        String tmpStr = "";
        if (itemStack.getType() == Material.ENCHANTED_BOOK) {
            if (itemMeta instanceof EnchantmentStorageMeta) {
                EnchantmentStorageMeta storageMeta = (EnchantmentStorageMeta) itemMeta;
                Map<Enchantment, Integer> storedEnchants = storageMeta.getStoredEnchants();
                for (Map.Entry<Enchantment, Integer> entry: storedEnchants.entrySet()) {
                    String enchantName = entry.getKey().getName();
                    Integer enchantLevel = entry.getValue();
                    if (tmpStr.length() == 0) {
                        tmpStr += "{\"name\":\"" + enchantName + "\",\"level\":\"" + enchantLevel + "\"}";
                    } else {
                        tmpStr += ",{\"name\":\"" + enchantName + "\",\"level\":\"" + enchantLevel + "\"}";
                    }
                }
                enchantStr += "[" + tmpStr + "]";
            } else {
                enchantStr = "[]";
            }
        } else {
            Map<Enchantment, Integer> enchants = itemStack.getItemMeta().getEnchants();
            for (Enchantment enchantment :enchants.keySet()) {
                String name = enchantment.getName();
                Integer level = enchants.get(enchantment);
                if (tmpStr.length() == 0) {
                    tmpStr += "{\"name\":\"" + name + "\",\"level\":\"" + level + "\"}";
                } else {
                    tmpStr += ",{\"name\":\"" + name + "\",\"level\":\"" + level + "\"}";
                }
            }
            enchantStr += "[" + tmpStr + "]";
        }
        return enchantStr;
    }

    private boolean setupEconomy() {
        try {
            RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
            if (rsp == null) {
                return false;
            }
            econ = rsp.getProvider();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取玩家金额
     */
    public static BigDecimal getPlayerMoney(Player player) {
        return new BigDecimal(econ.getBalance(player));
    }

    /**
     * 扣除玩家金额
     * @param player 要扣除金额的玩家
     * @param money 要扣除的金额
     * @return 扣除金额后的玩家余额
     */
    public static BigDecimal reducePlayerMoney(Player player, BigDecimal money) {
        // 获取玩家的当前余额
        BigDecimal currentBalance = new BigDecimal(econ.getBalance(player));

        // 计算扣除金额后的新余额
        BigDecimal newBalance = currentBalance.subtract(money);

        // 更新玩家的余额
        econ.withdrawPlayer(player, money.doubleValue());

        // 返回扣除金额后的玩家余额
        return newBalance;
    }

    /**
     * 给在线的玩家打钱
     * @param player 要打钱的玩家
     * @param money 要打钱的金额
     * @return 打钱后的玩家余额
     */
    public static BigDecimal increasePlayerMoney(Player player, BigDecimal money) {
        // 获取玩家的当前余额
        BigDecimal currentBalance = new BigDecimal(econ.getBalance(player));

        // 计算加钱后的新余额
        BigDecimal newBalance = currentBalance.add(money);

        // 更新玩家的余额
        econ.depositPlayer(player, money.doubleValue());

        // 返回加钱后的玩家余额
        return newBalance;
    }

    private void sendMessageToPlayer(Player player) {
        String inventoryName = config.getString("market.name");
        player.sendMessage(config.getString("notice.title"));
        player.sendMessage(inventoryName + config.getString("notice.tip"));
        player.sendMessage(inventoryName + config.getString("notice.buyMsg"));
        player.sendMessage(inventoryName + config.getString("notice.listMsg"));
        player.sendMessage(inventoryName + config.getString("notice.saleMsg"));
        player.sendMessage(inventoryName + config.getString("notice.sellMsg"));
        player.sendMessage(inventoryName + config.getString("notice.leaseMsg"));
    }
}
